home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-02 / drawer.zip / MOUSE.PAS < prev    next >
Pascal/Delphi Source File  |  1993-01-04  |  16KB  |  565 lines

  1. {$R-,S-,L-,D-}
  2. UNIT mouse;
  3.  
  4. {=============================================================
  5.  
  6.     MOUSE.PAS   Low-level mouse unit for QuickPascal
  7.  
  8.     Real mode Mouse control routines.  Derived from
  9.     Microsoft OS/2 Programmer's Reference, chapter 3.
  10.  
  11. ==============================================================}
  12.  
  13. INTERFACE
  14.  
  15. CONST
  16.     { button masks }
  17.     left_b    = $0001;
  18.     right_b   = $0002;
  19.     center_b  = $0004;
  20.  
  21.     { call masks }
  22.     pos_changed    = $0001;
  23.     left_press     = $0002;
  24.     left_release   = $0004;
  25.     right_press    = $0008;
  26.     right_release  = $0010;
  27.     center_press   = $0020;
  28.     center_release = $0040;
  29.  
  30.     { text pointer selectors }
  31.     software_pointer = 0;
  32.     hardware_pointer = 1;
  33.  
  34. VAR
  35.     { indicates the presence of a mouse
  36.       initialized in unit startup
  37.     }
  38.     mouse_present : Boolean;
  39.  
  40. { See the IMPLEMENTATION section for full descriptions of each
  41.   procedure and function.
  42. }
  43. FUNCTION  ms_init( VAR nButtons : Integer ) : Boolean;
  44. PROCEDURE ms_show;
  45. PROCEDURE ms_hide;
  46. PROCEDURE ms_read( VAR x, y, b_mask : Word );
  47. PROCEDURE ms_read_motion ( VAR hCount, vCount : Word );
  48. PROCEDURE ms_set_pos( x, y : Word );
  49.  
  50. PROCEDURE ms_lightpen_on;
  51. PROCEDURE ms_lightpen_off;
  52.  
  53. FUNCTION  ms_get_b(     b_mask         : Word;
  54.                     VAR count          : Word;
  55.                     VAR last_x, last_y : Word ) : Word;
  56. FUNCTION  ms_get_b_release(     b_mask         : Word;
  57.                             VAR count          : Word;
  58.                             VAR last_x, last_y : Word ):Word;
  59.  
  60. PROCEDURE ms_set_hminmax( min, max : Word );
  61. PROCEDURE ms_set_vminmax( min, max : Word );
  62. PROCEDURE ms_set_graphPointer( hotx, hoty : Word;
  63.                                image      : POINTER );
  64. PROCEDURE ms_set_textPointer( select       : Word;
  65.                               screen_char  : Char;
  66.                               screen_attr  : Byte;
  67.                               pointer_char : Char;
  68.                               pointer_attr : Byte );
  69.  
  70. PROCEDURE ms_set_MPP( hMPP, vMPP : Word );
  71. PROCEDURE ms_cond_off( top, left, bottom, right : Word );
  72. PROCEDURE ms_set_2speed( MPS : Word );
  73.  
  74. PROCEDURE ms_set_routine( call_mask : Word; sub : POINTER );
  75. PROCEDURE ms_swap_routine(     call_mask      : Word;
  76.                                sub            : POINTER;
  77.                            VAR last_call_mask : Word;
  78.                            VAR last_sub       : POINTER );
  79.  
  80. FUNCTION  ms_get_state_bfsz : Word;
  81. PROCEDURE ms_get_state( ms_state : POINTER );
  82. PROCEDURE ms_set_state( ms_state : POINTER );
  83.  
  84.  
  85. {=============================================================}
  86.                      IMPLEMENTATION
  87. {=============================================================}
  88.  
  89. USES  Dos;
  90.  
  91. CONST
  92.     ms_call = $33;  { mouse interrupt number }
  93.     iret    = $cf;  { iret (return from interrupt) instruction }
  94. VAR
  95.     r  : Registers; { scratch Registers variable }
  96.     mi : Pointer;   { mouse interrupt vector for initial test }
  97.  
  98. { The following functions are used to unpack pointers
  99.   into segment and offset
  100. }
  101. FUNCTION PSeg( x : POINTER ) : Word; INLINE( $5a/$58 );
  102. FUNCTION POfs( x : POINTER ) : Word; INLINE( $58/$5a );
  103.  
  104. {==============================================================
  105.     ms_init                          real-mode mouse function 0
  106.  ==============================================================
  107.     Return True and initialize the mouse if a mouse device is
  108.     present, False if no mouse present.
  109.  
  110.     nButtons contains the number of buttons on the mouse.
  111.  
  112.     The mouse is initialized to the following default values:
  113.         position                  : screen center
  114.         pointer-draw flag         : -1 (pointer hidden)
  115.         graphics pointer          : default image
  116.         text pointer              : reverse video
  117.         interrupt mask            : 0, no user routine in use
  118.         light pen emulation       : on
  119.         Mickeys/pixel(horizontal) :  8:8
  120.         Mickeys/pixel(vertical)   : 16:8
  121.         min/max position          : depends on display mode
  122. }
  123. FUNCTION ms_init( VAR nButtons : Integer ) : Boolean;
  124.     BEGIN
  125.     IF mouse_present THEN
  126.         BEGIN
  127.         r.AX := 0;
  128.         Intr( ms_call, r );
  129.         IF r.AX = 0 THEN    { no mouse }
  130.             BEGIN
  131.             nButtons := 0;
  132.             ms_init  := False;
  133.             END
  134.         ELSE
  135.             BEGIN
  136.             nButtons := r.BX;
  137.             ms_init  := True;
  138.             END;
  139.         END
  140.     ELSE
  141.         BEGIN
  142.         nButtons := 0;
  143.         ms_init := False;
  144.         END;
  145.     END;
  146.  
  147.  
  148. {==============================================================
  149.     ms_show                          real-mode mouse function 1
  150.  ==============================================================
  151.     If already visible, then do nothing.
  152.     If pointer-draw flag is nonzero, increment flag,
  153.     if pointer-draw flag is incremented to zero, display the
  154.     pointer image.
  155. }
  156. PROCEDURE ms_show;
  157.     BEGIN
  158.     r.AX := 1;
  159.     Intr( ms_call, r );
  160.     END;
  161.  
  162. {==============================================================
  163.     ms_hide                          real-mode mouse function 2
  164.  ==============================================================
  165.     Decrement pointer-draw flag.
  166.     If pointer already hidden, then return.
  167.     If pointer-draw flag is decremented to -1, then pointer is
  168.     hidden.
  169.     Always decrements pointer-draw flag.
  170. }
  171. PROCEDURE ms_hide;
  172.     BEGIN
  173.     r.AX:=2;
  174.     Intr( ms_call, r );
  175.     END;
  176.  
  177.  
  178. {==============================================================
  179.     ms_read                          real-mode mouse function 3
  180.  ==============================================================
  181.     Read mouse button state(s) and screen coordinates of the
  182.     pointer screen coordinates are relative to the range for
  183.     virtual screen (mode-dependent).
  184.     Button is pressed if bit is set:
  185.         2-button mouse:
  186.             bit 0 = left button
  187.             bit 1 = right button
  188.         3-button mouse:
  189.             bit 0 = left button
  190.             bit 1 = right button
  191.             bit 2 = Center button
  192. }
  193. PROCEDURE ms_read( VAR x, y, b_mask : Word );
  194.     BEGIN
  195.     r.AX := 3;
  196.     Intr( ms_call, r );
  197.     x := r.CX;
  198.     y := r.DX;
  199.     b_mask := r.BX;
  200.     END;
  201.  
  202.  
  203. {==============================================================
  204.     ms_set_pos                       real-mode mouse function 4
  205.  ==============================================================
  206.     set mouse position
  207.     x and y are clipped to min/max values
  208. }
  209. PROCEDURE ms_set_pos( x, y : Word );
  210.     BEGIN
  211.     r.AX := 4;
  212.     r.CX := x;
  213.     r.DX := y;
  214.     Intr( ms_call, r );
  215.     END;
  216.  
  217.  
  218. {==============================================================
  219.     ms_get_b                      real-mode mouse function 5
  220.  ==============================================================
  221.     Return mouse button-press status.
  222.     count contains the number of times button was pressed since
  223.     since the last call to this function. The count is reset to
  224.     zero.
  225.     Does not detect button-press counter overflow.
  226.     last_x, last_y are the screen coordinates of the pointer at
  227.     the last button press.
  228. }
  229. FUNCTION ms_get_b(     b_mask : Word;
  230.                    VAR count, last_x, last_y : Word ) : Word;
  231.     BEGIN
  232.     r.AX := 5;
  233.     r.BX := b_mask;
  234.     Intr( ms_call, r );
  235.  
  236.     count    := r.BX;
  237.     last_x   := r.CX;
  238.     last_y   := r.DX;
  239.     ms_get_b := r.AX;
  240.     END;
  241.  
  242.  
  243. {==============================================================
  244.     ms_get_b_release              real-mode mouse function 6
  245.  ==============================================================
  246.     returns mouse button release status
  247.     count contains the number of times button was released
  248.     since the last call to this function.  The count is reset
  249.     to zero.
  250.     Does not detect button-release counter overflow.
  251.     last_x, last_y are the screen coordinates of the pointer at
  252.     the last button release.
  253. }
  254. FUNCTION ms_get_b_release(     b_mask         : Word;
  255.                            VAR count          : Word;
  256.                            VAR last_x, last_y : Word ) : Word;
  257.     BEGIN
  258.     r.AX := 6;
  259.     r.BX := b_mask;
  260.     Intr( ms_call, r );
  261.  
  262.     count  := r.BX;
  263.     last_x := r.CX;
  264.     last_y := r.DX;
  265.     ms_get_b_release := r.AX;
  266.     END;
  267.  
  268.  
  269. {==============================================================
  270.     ms_set_hminmax                   real-mode mouse function 7
  271.  ==============================================================
  272.     set horizontal mouse movement constraint range
  273.     if min>max then they are swapped
  274.     min/max are clipped to virtual screen size
  275.     if mouse pointer is outside the range, it is moved to just
  276.     inside the range
  277. }
  278. PROCEDURE ms_set_hminmax( min, max : Word );
  279.     BEGIN
  280.     r.AX := 7;
  281.     r.CX := min;
  282.     r.DX := max;
  283.     Intr( ms_call, r );
  284.     END;
  285.  
  286.  
  287. {==============================================================
  288.     ms_set_vminmax                   real-mode mouse function 8
  289.  ==============================================================
  290.     set vertical mouse movement constraint range
  291.     if min>max then they are swapped
  292.     min/max are clipped to virtual screen size
  293.     if mouse pointer is outside the range, it is moved to just
  294.     inside the range
  295. }
  296. PROCEDURE ms_set_vminmax( min, max : Word );
  297.     BEGIN
  298.     r.AX := 8;
  299.     r.CX := min;
  300.     r.DX := max;
  301.     Intr( ms_call, r );
  302.     END;
  303.  
  304.  
  305. {==============================================================
  306.     ms_set_graphPointer              real-mode mouse function 9
  307.  ==============================================================
  308.     hotx, hoty (+/-16) are the hot spot coordinates relative to
  309.     the upper-left of the pointer image.
  310.     image = pointer to the mouse pointer image bitmap
  311.         The first 32 bytes define the screen mask
  312.         The last 32 bytes define the pointer mask
  313.     The pointer is drawn by:
  314.         AND screen mask with pixels under the pointer,
  315.         XOR pointer mask with result
  316.     In mode 6, each bit defines the color of a pixel.
  317.     In modes 4 and 5, each pair of bits defines the color of a
  318.     pixel.
  319. }
  320. PROCEDURE ms_set_graphPointer( hotx, hoty : Word;
  321.                                image      : POINTER );
  322.     BEGIN
  323.     r.AX := 9;
  324.     r.BX := hotx;
  325.     r.CX := hoty;
  326.     r.DX := POfs(image);
  327.     r.ES := PSeg(image);
  328.     Intr( ms_call, r );
  329.     END;
  330.  
  331.  
  332. {==============================================================
  333.     ms_set_textPointer              real-mode mouse function 10
  334.  ==============================================================
  335.     select determines which pointer: software or hardware
  336. }
  337. PROCEDURE ms_set_textPointer( select       : Word;
  338.                               screen_char  : Char;
  339.                               screen_attr  : Byte;
  340.                               pointer_char : Char;
  341.                               pointer_attr : Byte );
  342.     BEGIN
  343.     r.AX := 10;
  344.     r.BX := select;
  345.     r.CL := Byte(screen_char);
  346.     r.CH := screen_attr;
  347.     r.DL := Byte(pointer_char);
  348.     r.DH := pointer_attr;
  349.     Intr( ms_call, r );
  350.     END;
  351.  
  352.  
  353. {==============================================================
  354.     ms_read_motion                  real-mode mouse function 11
  355.  ==============================================================
  356.     Return the number of Mickeys the mouse has moved since the
  357.     last call to this function.
  358.     A positive number is right/down.
  359.     Reset counter to zero.
  360. }
  361. PROCEDURE ms_read_motion( VAR hCount, vCount : Word );
  362.     BEGIN
  363.     r.AX := 11;
  364.     Intr( ms_call, r );
  365.     hCount := r.CX;
  366.     vCount := r.DX;
  367.     END;
  368.  
  369.  
  370. {==============================================================
  371.     ms_set_routine                  real-mode mouse function 12
  372.  ==============================================================
  373.     Set the call mask and subroutine address for user-defined
  374.     mouse hardware interrupt handler.
  375. }
  376. PROCEDURE ms_set_routine( call_mask : Word; sub : POINTER );
  377.     BEGIN
  378.     r.AX := 12;
  379.     r.CX := call_mask;
  380.     r.DX := POfs(sub);
  381.     r.ES := PSeg(sub);
  382.     Intr( ms_call, r );
  383.     END;
  384.  
  385.  
  386. {==============================================================
  387.     ms_lightpen_on                  real-mode mouse function 13
  388.  ==============================================================
  389.     turn light pen emulation on
  390. }
  391. PROCEDURE ms_lightpen_on;
  392.     BEGIN
  393.     r.AX := 13;
  394.     Intr( ms_call, r );
  395.     END;
  396.  
  397.  
  398. {==============================================================
  399.     ms_lightpen_off                 real-mode mouse function 14
  400.  ==============================================================
  401.     turn light pen emulation off
  402. }
  403. PROCEDURE ms_lightpen_off;
  404.     BEGIN
  405.     r.AX := 14;
  406.     Intr( ms_call, r );
  407.     END;
  408.  
  409.  
  410. {==============================================================
  411.     ms_set_MPP                      real-mode mouse function 15
  412.  ==============================================================
  413.     set horizontal and vertical mouse motion rates
  414.     MPP (1 <= MPP <= 32767) = Mickeys / 8 pixels
  415.     default hMPP is 8:8
  416.     default vMPP is 16:8
  417. }
  418. PROCEDURE ms_set_MPP( hMPP, vMPP : Word );
  419.     BEGIN
  420.     IF (hMPP >= 1) AND (hMPP <= 32767) AND
  421.        (vMPP >= 1) AND (vMPP <= 32767) THEN
  422.         BEGIN
  423.         r.AX := 15;
  424.         r.CX := hMPP;
  425.         r.DX := vMPP;
  426.         Intr( ms_call, r );
  427.         END;
  428.     END;
  429.  
  430.  
  431. {================================================================
  432.     ms_cond_off                       real-mode mouse function 16
  433.  ================================================================
  434.     If the pointer is in the defined region, function 16 hides
  435.     the pointer while the region is being updated.
  436.     After this call is issued, you must call function 1
  437.     (ms_show) to show the pointer again.
  438.     Coordinates specified in pixels.
  439. }
  440. PROCEDURE ms_cond_off( top, left, bottom, right : Word );
  441.     BEGIN
  442.     r.AX := 16;
  443.     r.CX := left;
  444.     r.DX := top;
  445.     r.SI := right;
  446.     r.DI := bottom;
  447.     Intr( ms_call, r );
  448.     END;
  449.  
  450.  
  451. {================================================================
  452.     ms_set_2speed                     real-mode mouse function 19
  453.  ================================================================
  454.     Set the threshold speed for doubling pointer motion to the
  455.     screen, specified in Mickeys Per Second
  456.     The default double speed threshold is 128 mickeys per second.
  457. }
  458. PROCEDURE ms_set_2speed( MPS : Word );
  459.     BEGIN
  460.     r.AX := 19;
  461.     r.DX := MPS;
  462.     Intr( ms_call, r );
  463.     END;
  464.  
  465.  
  466. {================================================================
  467.     ms_swap_routine                   real-mode mouse function 20
  468.  ================================================================
  469.     Set call mask and user-defined interrupt routine,
  470.     return previous call mask and interrupt vector.
  471.  
  472.     The Quick Pascal header for the mouse interrupt handler
  473.     would be:
  474.  
  475.     PROCEDURE myMouseInt( Flags, CS, IP,  (* not used *)
  476.                           condition_mask,
  477.                           b_state,
  478.                           hPos, vPos,
  479.                           lastVM, lastHM : Word ); INTERRUPT;
  480.  
  481.     The interrupt routine will be called with the following
  482.     values in the registers:
  483.         AX : condition mask (bit set = condition occurred)
  484.         BX : button state
  485.         CX : horizontal pointer coordinate
  486.         DX : vertical pointer coordinate
  487.         SI : last raw vertical Mickey count
  488.         DI : last raw horizontal Mickey count
  489.  
  490.     DS will contain the segment address of the mouse driver's
  491.     data segment, so the interrupt routine must set DS to it's
  492.     own data segment.
  493.  
  494. }
  495. PROCEDURE ms_swap_routine(     call_mask      : Word;
  496.                                sub            : POINTER;
  497.                            VAR last_call_mask : Word;
  498.                            VAR last_sub       : POINTER );
  499.     BEGIN
  500.     r.AX := 20;
  501.     r.CX := call_mask;
  502.     r.DX := POfs(sub);
  503.     r.ES := PSeg(sub);
  504.     Intr( ms_call, r );
  505.  
  506.     last_call_mask := r.CX;
  507.     last_sub := Ptr( r.ES, r.DX );
  508.     END;
  509.  
  510.  
  511. {================================================================
  512.     ms_get_state_bfsz              real-mode mouse function 21
  513.  ================================================================
  514.     Return buffer size in bytes required to save the mouse driver
  515.     state.
  516. }
  517. FUNCTION ms_get_state_bfsz: Word;
  518.     BEGIN
  519.     r.AX := 21;
  520.     Intr( ms_call, r );
  521.     ms_get_state_bfsz := r.BX;
  522.     END;
  523.  
  524.  
  525. {================================================================
  526.     ms_get_state                      real-mode mouse function 22
  527.  ================================================================
  528.     Get the mouse driver state.
  529. }
  530. PROCEDURE ms_get_state( ms_state : POINTER );
  531.     BEGIN
  532.     r.AX := 22;
  533.     r.DX := POfs(ms_state);
  534.     r.ES := PSeg(ms_state);
  535.     Intr( ms_call, r );
  536.     END;
  537.  
  538.  
  539. {================================================================
  540.     ms_set_state                      real-mode mouse function 23
  541.  ================================================================
  542.     Set mouse driver state, given a previously saved state.
  543. }
  544. PROCEDURE ms_set_state( ms_state : POINTER );
  545.     BEGIN
  546.     r.AX := 23;
  547.     r.DX := POfs(ms_state);
  548.     r.ES := PSeg(ms_state);
  549.     Intr( ms_call, r );
  550.     END;
  551.  
  552.  
  553. {=============== initialization =================================}
  554. BEGIN
  555.  
  556. GetIntVec( ms_call, mi );
  557. IF mi = NIL THEN               { mouse interrupt vector null }
  558.     mouse_present := False
  559. ELSE IF Byte(mi^) = iret THEN  { vector points to iret }
  560.     mouse_present := False
  561. ELSE
  562.     mouse_present := True;
  563.  
  564. END. { mouse unit }
  565.